import re

from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from django_redis import get_redis_connection
from rest_framework import serializers
from rest_framework.serializers import ModelSerializer
from rest_framework_simplejwt.serializers import TokenObtainPairSerializer

from config.dbs.redisConfig import KEY_TEMPLATE
from users.models import UserDetail, Area, Address


class UserSerializer(ModelSerializer):
    uuid = serializers.CharField(write_only=True)
    verify = serializers.CharField(write_only=True)
    sex = serializers.IntegerField(read_only=True, source='userdetail.sex')
    birthday = serializers.DateField(read_only=True, source='userdetail.birthday')
    # email = serializers.CharField(read_only=True)
    phone = serializers.CharField(read_only=True, source='userdetail.phone')
    avatar = serializers.ImageField(read_only=True, source='userdetail.avatar')

    class Meta:
        model = User
        fields = '__all__'
        # 过滤不给用户查看的字段信息
        # exclude = ['first_name', 'last_name', "user_permissions", 'last_login', 'date_joined', "groups"]
        # 限制字段为只写字段 限制字段为只读字段
        extra_kwargs = {
            "is_superuser": {"read_only": True},
            "is_staff": {"read_only": True},
            "is_active": {"read_only": True},
            'password': {'write_only': True}
        }

    def validate(self, attrs):
        uuid = attrs.get('uuid')
        verify = attrs.get('verify')
        # redis 查询正确的答案是什么
        cache = get_redis_connection(alias='verify_codes')
        redis_verify = cache.get(KEY_TEMPLATE % ('register', uuid))
        # 删除验证码 让这个验证码过期，防止暴力破解
        cache.delete(KEY_TEMPLATE % ('register', uuid))
        if not redis_verify:
            raise serializers.ValidationError("验证码过期")
        # 校验两个验证码是否一致
        if redis_verify.upper() != verify.upper():
            raise serializers.ValidationError("验证码错误")
        return attrs


class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
    # 添加两个字段显示给用户看
    # 需要uuid唯一标识
    uuid = serializers.CharField(write_only=True)
    # 验证码字典
    verify = serializers.CharField(write_only=True)

    def validate(self, attrs):
        uuid = attrs.get('uuid')
        verify = attrs.get('verify')
        username = attrs.get('username')
        password = attrs.get('password')
        # redis 查询正确的答案是什么
        cache = get_redis_connection(alias='verify_codes')
        redis_verify = cache.get(KEY_TEMPLATE % ('login', uuid))
        # 删除验证码 让这个验证码过期，防止暴力破解
        cache.delete(KEY_TEMPLATE % ('login', uuid))
        if not redis_verify:
            raise serializers.ValidationError("验证码过期")
        # 校验两个验证码是否一致
        if redis_verify.upper() != verify.upper():
            raise serializers.ValidationError("验证码错误")
        # 程序能够正常执行到这一步 意味着验证码校验没有问题
        # 可以身份的校验 auth系统的校验 用户名和密码
        user = authenticate(username=username, password=password)
        if not user:
            raise serializers.ValidationError("账号或密码错误")
        # 生成用户的令牌信息
        refresh = self.get_token(user)
        return {"user": user.username, 'token': str(refresh.access_token)}


class UserDetailSerializer(ModelSerializer):
    class Meta:
        model = UserDetail
        exclude = ['is_delete']


class UpdatePasswordSerializer(serializers.Serializer):
    password = serializers.CharField(max_length=60, label="原密码", help_text="原密码")
    new_password = serializers.CharField(max_length=60, label="新密码", help_text="新密码")
    re_new_password = serializers.CharField(max_length=60, label="确认新密码", help_text="确认新密码")

    def validate(self, attrs):
        if attrs['new_password'] != attrs['re_new_password']:
            raise serializers.ValidationError("两次密码输入不一致")
        if attrs["password"] == attrs['re_new_password']:
            raise serializers.ValidationError("新密码与旧密码一致，无需操作")
        return attrs


class AreaSerializer(ModelSerializer):
    class Meta:
        model = Area
        fields = '__all__'


class ParentAreaSerializer(ModelSerializer):
    area_set = AreaSerializer(many=True, read_only=True)

    class Meta:
        model = Area
        fields = '__all__'


class AddressSerializer(ModelSerializer):
    province_name = serializers.CharField(source='province.name', read_only=True)
    city_name = serializers.CharField(source='city.name', read_only=True)
    district_name = serializers.CharField(source='district.name', read_only=True)

    class Meta:
        model = Address
        fields = '__all__'

    def validate_mobile(self, value):
        if not re.findall(r'^1[3-9]\d{9}$', value):
            raise serializers.ValidationError("手机号码格式错误")
        return value
